package com.example.mqsender; /**
 * Dans.com Inc. Copyright (c) 2011-2020 All Rights Reserved
 */


import com.example.mqsender.config.RabbitMQConfig;
import lombok.extern.slf4j.Slf4j;
import notify.Message;
import notify.MessageSender;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 字典服务消息发送处理类
 *
 * @author ke
 * <p>
 * Created by on 2021-05-16 15:52
 */

@Component
@Slf4j
public class MQEventSender implements MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig config;


    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (!ack) {

                /**
                 * 通过日志记录发送失败的id，从而提醒系统异常，会导致业务失败
                 */
                log.error("send message error cause:{},correlationData:{}", cause, correlationData);
                throw new RuntimeException("send message error cause:" + cause + ",correlationData:" + correlationData);
            }
        });
    }


    /**
     * 如果在sender中不catch异常，直接将未确认的消息爆出异常，导致业务异常，由业务补偿
     * 如果实在是非常非常重要的业务，且不能失败的业务，请重新实现sender方法，使用rabbitmq的同步事物发送消息，保证消息到达broker， 但是此方法性能极地，只有几百tps，不推荐使用，如果业务需要可以考虑实现
     * 还有一种方式是通过cache记录发送失败的消息，在ack到达后再进行删除，然后在由业务线程对失败的消息进行重试和处理，这里不再实现当前方法
     *
     * @param message
     */

    @Override
    public void send(Message message) {
        rabbitTemplate.convertAndSend(config.getExchangeName(), config.getRoutingKey(), message);

    }
}

